package com.sojson.util;

import static com.sojson.constant.ConstantByMap.EXCEL_PATH;
import static com.sojson.constant.ConstantByMap.IMG_PATH;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import com.sojson.result.Result;
import com.sojson.util.file.FileDepotUtil;
import com.sojson.util.file.FileUtil;
import com.sojson.util.file.enums.EFileType;
import com.sojson.util.httpclient.HttpClientUtil;

import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;

public class ToolsUtil {

    /** 工资模板文件基础路径 */
    public static final String SALARY_EXCEL_TEMPATE_PATH = EXCEL_PATH + "/salary/template.xlsx";
    /** 头像文件基础路径 */
    public static final String HEAD_IMG_PATH = IMG_PATH + "/head";
    /** 用户身份证基础路径 */
    public static final String ID_CARD = IMG_PATH + "/idCard";
    /** 验证码图片基础路径 */
    public static final String VERIFY_IMG = IMG_PATH + "/verifyImg";
    /** 企业资质照片文件基础路径 */
    public static final String BUSINESS_CERT_IMG_PATH = IMG_PATH + "/businessCert";
    /** 商品分类缩略图文件基础路径 */
    public static final String GOOD_CATE_THUMB = IMG_PATH + "/good/cateThumb";
    /** 商品缩略图文件基础路径 */
    public static final String GOOD_THUMB = IMG_PATH + "/good/thumb";
    /** 商品详情轮播图文件基础路径 */
    public static final String GOOD_IMAGES = IMG_PATH + "/good/images";
    /** 商品规格明细缩略图文件基础路径 */
    public static final String GOOD_SPECS_ATTR_THUMB = IMG_PATH + "/good/specsAttrThumb";
    /** 评论图片文件基础路径 */
    public static final String COMMENT_IMG_PATH = IMG_PATH + "/comment";
    /** 广告图片基础路径 */
    public static final String AD = IMG_PATH + "/ad";
    /** 许可证基础路径 */
    public static final String BUSINESS_LICENSE = IMG_PATH + "/uploadBusinessLicense";
    /** 图片类型白名单 */
    public static final String[] IMG_WHITE_LIST = new String[] {"image/png"};
    /** 图片大小 */
    public static final int IMG_SIZE = 10 * 1024 * 1024;
    /** resources路径 */
    public static final String RESOURCES_PATH = getResourcesPath();

    public static String getResourcesPath() {
        try {
            return new ClassPathResource("").getURL().getPath().substring(1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * MD5加密
     *
     * @return String
     */
    public static String md5(String content) {
        return DigestUtils.md5DigestAsHex(content.getBytes());
    }

    /**
     * 获取随机数
     *
     * @param len 生成的长度
     * @return
     */
    public static String random(Integer len) {
        String seed = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghjkmnpqrstuvwxyz";
        String[] seedArr = seed.split("");
        // 生成数组结果
        char[] res = new char[len];

        Random random = new Random();
        int arrLen = seedArr.length;

        for (int i = 0; i < len; i++) {
            res[i] = seedArr[random.nextInt(arrLen)].charAt(0);
        }

        return new String(res);
    }

    /**
     * 获取客户端IP
     *
     * @param request
     * @return
     */
    public static String getIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return ip;

    }

    /**
     * 上传
     *
     * @param file 上传的文件
     * @param path 存储路径
     * @param mimeTypeWhiteList 限制的文件mime
     * @param size 限制的文件大小 KB
     * @return
     * @throws Exception 
     */
    public static Result<String> upload(MultipartFile file, String path, String[] mimeTypeWhiteList, double size)
        throws Exception {
        if (StringUtil.isBlankObject(mimeTypeWhiteList) || StringUtil.isBlankObject(file) || file.isEmpty()) {
            return Result.fail("文件不能为空");
        }

        String fileName = file.getOriginalFilename();
        int fileSize = (int)file.getSize();
        // 验证大小
        if (size < fileSize) {
            return Result.fail("文件过大，最大允许上传" + String.format("%.2f", size / 1024 / 1024) + "M");
        }

        // 验证mime,文件类型
        // boolean mimeRes = mimeTypeCheck(file, mimeTypeWhiteList);
        //
        // if (mimeRes == false) {
        // return Result.fail("文件类型不允许");
        // }

        String uploadingToThisLocalityDirectory = FileUtil.uploadingToThisLocalityDirectory(file.getBytes(),
            fileName.substring(fileName.lastIndexOf(".")), path);

        try {
            boolean uploadThisLocal = FileDepotUtil.uploadThisLocal(uploadingToThisLocalityDirectory);
            if (!uploadThisLocal) {
                FileDepotUtil.deleteFileThisLocalByUrl(uploadingToThisLocalityDirectory);
                return Result.fail("添加图片关联关系失败！");
            }
        } catch (Exception e) {
            FileDepotUtil.deleteFileThisLocalByUrl(uploadingToThisLocalityDirectory);
            return Result.fail("添加图片关联关系失败，" + e.getMessage());
        }
        return Result.success("上传成功", uploadingToThisLocalityDirectory);
    }

    /**
     * 上传
     *
     * @param file 上传的文件
     * @param path 存储路径
     * @param mimeTypeWhiteList 限制的文件mime
     * @param size 限制的文件大小 KB
     * @return
     * @throws Exception 
     */
    public static Result<List<String>> upload(MultipartFile[] files, String path, String[] mimeTypeWhiteList,
        double size) throws Exception {
        int length = files.length;
        if (StringUtil.isBlankObject(mimeTypeWhiteList) || StringUtil.isBlankObject(files) || length < 1) {
            return Result.fail("文件不能为空");
        }

        for (int i = 0; i < length; i++) {
            MultipartFile file = files[i];
            String fileName = file.getOriginalFilename();
            int fileSize = (int)file.getSize();
            // 验证大小
            if (size < fileSize) {
                return Result.fail(fileName + "文件过大，最大允许上传" + String.format("%.2f", size / 1024 / 1024) + "M");
            }

            // 验证mime,文件类型
            // boolean mimeRes = mimeTypeCheck(file, mimeTypeWhiteList);
            //
            // if (mimeRes == false) {
            // return Result.fail(fileName + "文件类型不允许");
            // }
        }

        List<String> arrayList = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            MultipartFile file = files[i];
            String fileName = file.getOriginalFilename();

            try {
                String uploadingToThisLocalityDirectory = FileUtil.uploadingToThisLocalityDirectory(file.getBytes(),
                    fileName.substring(fileName.lastIndexOf(".")), path);
                arrayList.add(uploadingToThisLocalityDirectory);

                boolean uploadThisLocal = FileDepotUtil.uploadThisLocal(uploadingToThisLocalityDirectory);
                if (!uploadThisLocal) {
                    FileDepotUtil.deleteFileThisLocalByUrl(arrayList);
                    return Result.fail("添加图片关联关系失败！");
                }
            } catch (Exception e) {
                FileDepotUtil.deleteFileThisLocalByUrl(arrayList);
                return Result.fail("添加图片关联关系失败，" + e.getMessage());
            }
        }
        return Result.success("上传成功", arrayList);
    }

    /**
     * 上传
     *
     * @param filePath 原文件地址
     * @param path 存储路径
     * @param mimeTypeWhiteList 限制的文件mime
     * @param size 限制的文件大小 KB
     * @return
     * @throws Exception 
     */
    public static Result<String> upload(String filePath, String path, String[] mimeTypeWhiteList, double size)
        throws Exception {
        byte[] bytes = HttpClientUtil.getBytes(filePath);
        if (StringUtil.isBlankObject(bytes)) {
            return Result.fail("获取文件失败");
        }
        EFileType fileType = FileUtil.getFileType(bytes);

        return Result.success("上传成功", FileUtil.uploadingToThisLocalityDirectory(bytes, fileType.getNameD(), path));
    }

    /**
     * 文件后缀名校验
     *
     * @param fileName
     * 文件名称
     * String[] suffixWhiteList = {"PNG","JPEG","JPG","GIF"};
     * @return
     */
    public static boolean suffixCheck(String fileName, String[] suffixWhiteList) {
        if (fileName == null || "".equals(fileName)) {
            return false;
        }
        // 从最后一个点之后截取字符串
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        // 白名单匹配
        boolean anyMatch = Arrays.stream(suffixWhiteList).anyMatch(x -> x.equalsIgnoreCase(suffix));
        return anyMatch;
    }

    /**
     * MIMETYPE校验
     *  String[] mimeTypeWhiteList = {"image/jpeg","image/gif","image/png"};
     * @return
     */

    public static boolean mimeTypeCheck(MultipartFile uploadFile, String[] mimeTypeWhiteList) {
        if (uploadFile.isEmpty()) {
            return false;
        }
        // 文件名
        String fileName = uploadFile.getOriginalFilename();
        // 获取文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        File picFile = null;
        try {
            // 用uuid作为文件名，防止生成的临时文件重复
            picFile = File.createTempFile(getUUID(), suffix);
            FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), picFile);
            // MultipartFile to File
            MagicMatch match = Magic.getMagicMatch(picFile, false);
            String mimeType = match.getMimeType();
            // 白名单匹配
            boolean anyMatch = Arrays.stream(mimeTypeWhiteList).anyMatch(x -> x.equalsIgnoreCase(mimeType));
            return anyMatch;

        } catch (IOException e) {
            // LOGGER.error("生成临时文件异常",e);
        } catch (Exception e) {
            // LOGGER.error("MIME-TYPE检查发生异常",e);
        } finally {
            // 程序结束时，删除临时文件
            if (picFile.exists()) {
                picFile.delete();
            }
        }
        return false;
    }

    /**
     * 生成随机字符串的工具类 uuid
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

}
